import { _decorator, Component, Node, Button, Label, Sprite } from 'cc';
import { BasePanel } from '../../../../scripts/libs/ui/BasePanel';
import { KeyDown } from '../../../../scripts/libs/rxjs/cc3/KeyEvent';
import { KeyCode } from 'cc';
import { lm } from '../../LobbyManager';
import { FlowStatus } from '../../Enums';
import { StageView } from './2d/StageView';
import { gm } from '../../../../scripts/managers/GameManager';
import { concat, Observable, of, Subscription } from 'rxjs';
import { BindButton } from '../../../../scripts/libs/rxjs/cc3/BindButton';
import { ResourceHelper } from '../../ResourceHelper';
import { MergeASAP } from '../../../../scripts/libs/rxjs/cc3/Merge';
import { find } from 'cc';
import { view } from 'cc';
import { udm } from '../../../../scripts/managers/UserDataManager';
import { LoseLifeTipPanel } from '../LoseLifeTipPanel/LoseLifeTipPanel';
import { thinking_sdk_m } from '../../../../scripts/managers/SDK/ThinkingCocosSDKManager';
import { BuyHeartPanel } from '../BuyHeartPanel/BuyHeartPanel';
import { ShopPanel } from '../ShopPanel/ShopPanel';
import { PausePanel } from '../PausePanel/PausePanel';
import { DevConfig, FeatureKey, FeatureParam, ItemKey, ItemParam } from '../../../../scripts/managers/DevConfig';
import { ItemUnlockPanel } from '../ItemUnlockPanel/ItemUnlockPanel';
import { BuyItemPanel } from '../BuyItemPanel/BuyItemPanel';
import { Animation } from 'cc';
import { DesignHeight } from '../../../../scripts/managers/ScreenManager';
import { linear } from '../../../../scripts/libs/utils/math';
import { UITransform } from 'cc';
import { ResourceManager } from '../../../../scripts/managers/ResourceManager';
import { ItemWaitingTip } from './ItemWaitingTip';
import { FeatureUnlockPanel } from '../FeatureUnlockPanel/FeatureUnlockPanel';
import { Vec3 } from 'cc';
import { ParticleSystem } from 'cc';
import { Timer } from '../../../../scripts/libs/rxjs/cc3/CreatorSchedule';
import { nc } from '../../../../scripts/libs/rxjs/NotificationCenter';
import { UIOpacity } from 'cc';
import { Burst0 } from '../../../Particle/Burst0/Burst0';
const { ccclass, property } = _decorator;

@ccclass('GamePanel')
export class GamePanel extends BasePanel {

    @property(StageView)
    stageView: StageView = null;

    @property(Label)
    stageIdLabel: Label = null;

    @property(Button)
    exitButton: Button = null;

    @property(Button)
    retryButton: Button = null;

    @property(Button)
    pauseButton: Button = null;

    @property(Button)
    editButton: Button = null;

    @property(Label)
    stageNumLabel: Label = null;

    @property(Button)
    swapperButton: Button = null;

    @property(Button)
    magnetButton: Button = null;

    @property(Button)
    balloonButton: Button = null;

    @property(Button)
    gamePauseButton: Button = null;

    @property(Node)
    bottomNode: Node = null;

    @property(Node)
    buttonsNode: Node = null;

    @property(ItemWaitingTip)
    itemWaitingTip: ItemWaitingTip = null;

    @property(Node)
    fxContainer: Node = null;

    @property(Node)
    topNode: Node = null;

    willBind(): void {
        this.stageView.gamePanel = this;
        this.adaptive();
    }

    useObserves() {
        return [
            gm.fullScreenChangedCommand.subscribe(_ => {
                this.adaptive();
            }),

            gm.editEnabled.subscribe(_ => {
                this.editButton.node.active = _;
            }),
            BindButton(this.exitButton).subscribe(this.exitButtonClicked.bind(this)),
            BindButton(this.retryButton).subscribe(this.retryButtonClicked.bind(this)),
            BindButton(this.pauseButton).subscribe(this.pauseButtonClicked.bind(this)),
            BindButton(this.editButton).subscribe(this.editButtonClicked.bind(this)),

            BindButton(this.gamePauseButton).subscribe(this.pauseButtonClicked.bind(this)),
            BindButton(this.swapperButton).subscribe(this.swapperButtonClicked.bind(this)),
            BindButton(this.magnetButton).subscribe(this.magnetButtonClicked.bind(this)),
            BindButton(this.balloonButton).subscribe(this.balloonButtonClicked.bind(this)),
            KeyDown().subscribe((_: KeyCode) => {
                if (_ == KeyCode.ESCAPE) {
                    lm.flowStatus.value = FlowStatus.EditorGame; // 返回编辑模式
                }
            }),
            gm.loadGameCommand.subscribe(this.loadStage.bind(this)),
            gm.loadNextGameCommand.subscribe(this.loadNextStage.bind(this)),

            MergeASAP(gm.swapperSelected, gm.balloonSelected, gm.magnetSelected).subscribe(this.refreshItemButtons.bind(this)),

            MergeASAP(udm.itemSwapper, udm.itemMagnet, udm.itemBalloon, gm.itemAnimatingFlags).subscribe(this.refreshItems.bind(this)),
            nc.subscribe('change_smoke', this.genChangeSmoke.bind(this)),

            gm.gameHudHide.subscribe(_ => {
                if (gm.gameHudHide.value) {
                    this.topNode.getComponent(UIOpacity).opacity = 0;
                    this.bottomNode.getComponent(UIOpacity).opacity = 0;
                } else {
                    this.topNode.getComponent(UIOpacity).opacity = 255;
                    this.bottomNode.getComponent(UIOpacity).opacity = 255;
                }
            })
        ];
    }

    onDestroyView(): void {
        this._sub_smoke_list.forEach(sub => sub.unsubscribe())
    }

    adaptive() {
        let height = view.getVisibleSize().height;
        let scale = linear(1650, 2400, .7, 1, height);
        // this.stageView.node.setScale(scale, scale, scale);
        this.buttonsNode.setScale(scale, scale, scale);

        let bottomHeight = linear(1650, 2400, 300, 500, height);
        this.bottomNode.getComponent(UITransform).height = bottomHeight;
    }

    afterClose(): Observable<string> {
        this.stageView.afterClose();
        return of(null);
    }

    start() {
        this.loadStage();
    }

    loadStage() {
        this.stageView.loadStage(gm.stageInfo.value);
        this.refreshStageId();
        this.refreshItemEnabled();

        concat(
            this.tryOpenItemUnlockPanel(),
            this.tryOpenFeatureUnlockPanel(),
        ).subscribe();
    }

    tryOpenItemUnlockPanel() {
        for (let key in DevConfig.ITEM_PARAM) {
            if (!udm.passedFlags.value.has(`unlock_${key}`)) {
                let param = DevConfig.ITEM_PARAM[key] as ItemParam;
                if (param.start_stage == this.stageView.stageInfo.stageId) {
                    return ItemUnlockPanel.StartProcess((panel: ItemUnlockPanel) => {
                        this.log('@tryOpenItemUnlockPanel', key);
                        panel.itemKey.value = key as ItemKey;
                    });
                }
            }
        }
        return of(null);
    }

    tryOpenFeatureUnlockPanel() {
        for (let key in DevConfig.FEATURE_PARAM) {
            let param = DevConfig.FEATURE_PARAM[key] as FeatureParam;
            if (param.start_stage == this.stageView.stageInfo.stageId) {
                return FeatureUnlockPanel.StartProcess((panel: FeatureUnlockPanel) => {
                    this.log('@tryOpenFeatureUnlockPanel', key);
                    panel.featureKey.value = key as FeatureKey;
                });
            }
        }
        return of(null);
    }

    exitButtonClicked() {
        // if (udm.getRemainMsToOverInfHeart() > 0) { // 无限体力
        //     udm.gameLose(this.stageView.stageInfo, 'quit');
        //     lm.flowStatus.value = FlowStatus.Lobby;
        // } else {
        LoseLifeTipPanel.StartProcess().subscribe(_ => {
            if (_ == 'leave') {
                udm.gameLose(this.stageView.stageInfo, 'quit');
                lm.flowStatus.value = FlowStatus.Lobby;
            }
        });
        // }
    }

    retryButtonClicked() {
        // if (udm.getRemainMsToOverInfHeart() > 0) { // 无限体力
        //     udm.gameLose(this.stageView.stageInfo, 'restart');
        //     this.loadStage();
        // } else {
        LoseLifeTipPanel.StartProcess().subscribe(_ => {
            if (_ == 'leave') {
                let heartCount = udm.getHeartCount();
                if (udm.getRemainMsToOverInfHeart() > 0 || heartCount >= 2) {
                    udm.gameLose(this.stageView.stageInfo, 'restart');
                    this.loadStage();
                } else if (heartCount == 1) {
                    // gm.restartGameCommand.execute({ waitStart: true });
                    BuyHeartPanel.StartProcess().subscribe(_ => {
                        if (_ == 'continue') {
                            udm.gameLose(this.stageView.stageInfo, 'restart');
                            this.loadStage();
                            // gm.restartGameCommand.execute({ waitStart: false });
                            // GameLosePanel.CloseProcess(null, 'again'); // ???
                        }
                    });
                } else {
                    thinking_sdk_m.requestTrack('Shoping_Open', {
                        OpenType: 'NoEnergy',
                        OpenWay: 'Battle',
                        IsNew: udm.isNew.value,
                        Level_ID: udm.stageNum.value,
                    });
                    ShopPanel.StartProcess().subscribe();
                }
            }
        });
        // }
    }

    pauseButtonClicked() {
        PausePanel.StartProcess((panel: PausePanel) => {
            panel.gamePanel = this;
        }).subscribe(_ => {
            if (_ == 'exit') {
                this.exitButtonClicked();
            } else if (_ == 'retry') {
                this.retryButtonClicked();
            } else if (_ == 'edit') {
                lm.flowStatus.value = FlowStatus.EditorGame; // 返回编辑模式
            }
        });
    }

    editButtonClicked() {
        lm.flowStatus.value = FlowStatus.EditorGame; // 返回编辑模式
    }

    loadNextStage() {
        lm.customLoadingReasons.add('load_stage');
        let targetStageId = gm.stageInfo.value.stageId + 1;
        ResourceHelper.LoadStageAssets(targetStageId).subscribe(stageInfo => {
            if (stageInfo != null) {
                lm.customLoadingReasons.delete('load_stage');
                if (stageInfo.stageId != null && stageInfo.stageId != targetStageId) {
                    this.warn('StageId in json is not match with stageId in file name.');
                    return;
                }
                stageInfo.stageId = targetStageId;
                gm.stageInfo.value = stageInfo;

                this.loadStage();

            } else {
                lm.customLoadingReasons.delete('load_stage');
            }
        });
    }

    refreshStageId() {
        this.stageIdLabel.string = `Stage: ${this.stageView.stageInfo.stageId}`;
        this.stageNumLabel.string = `${this.stageView.stageInfo.stageId}`;
    }

    refreshItemEnabled() {
        let curStageId = this.stageView.stageInfo.stageId;


        if (curStageId >= DevConfig.ITEM_PARAM['swapper'].start_stage) {
            find('normal', this.swapperButton.node).active = true;
            find('lock', this.swapperButton.node).active = false;
        } else {
            find('normal', this.swapperButton.node).active = false;
            find('lock', this.swapperButton.node).active = true;
            find('lock/stageNum', this.swapperButton.node).getComponent(Label).string = `Level ${DevConfig.ITEM_PARAM['swapper'].start_stage}`;
        }

        if (curStageId >= DevConfig.ITEM_PARAM['magnet'].start_stage) {
            find('normal', this.magnetButton.node).active = true;
            find('lock', this.magnetButton.node).active = false;
        } else {
            find('normal', this.magnetButton.node).active = false;
            find('lock', this.magnetButton.node).active = true;
            find('lock/stageNum', this.magnetButton.node).getComponent(Label).string = `Level ${DevConfig.ITEM_PARAM['magnet'].start_stage}`;
        }

        if (curStageId >= DevConfig.ITEM_PARAM['balloon'].start_stage) {
            find('normal', this.balloonButton.node).active = true;
            find('lock', this.balloonButton.node).active = false;
        } else {
            find('normal', this.balloonButton.node).active = false;
            find('lock', this.balloonButton.node).active = true;
            find('lock/stageNum', this.balloonButton.node).getComponent(Label).string = `Level ${DevConfig.ITEM_PARAM['balloon'].start_stage}`;
        }


        // if (gm.editEnabled.value) {
        //     this.swapperButton.node.active = true;
        //     this.magnetButton.node.active = true;
        //     this.balloonButton.node.active = true;
        // } else {
        //     this.swapperButton.node.active = curStageId >= DevConfig.ITEM_PARAM['swapper'].start_stage;
        //     this.magnetButton.node.active = curStageId >= DevConfig.ITEM_PARAM['magnet'].start_stage;
        //     this.balloonButton.node.active = curStageId >= DevConfig.ITEM_PARAM['balloon'].start_stage;
        // }
    }

    refreshItemButtons() {
        // find('direction', this.swapperButton.node).active = gm.swapperSelected.value;
        // find('direction', this.balloonButton.node).active = gm.balloonSelected.value;
        // find('direction', this.magnetButton.node).active = gm.magnetSelected.value;

        if (gm.swapperSelected.value) {
            this.itemWaitingTip.itemKey.value = 'swapper';
        } else if (gm.balloonSelected.value) {
            this.itemWaitingTip.itemKey.value = 'balloon';
        } else {
            this.itemWaitingTip.itemKey.value = null;
        }
    }

    refreshItems() {
        if (gm.itemAnimatingFlags.size > 0) return;
        if (udm.itemSwapper.value > 0) {
            find('normal/plus', this.swapperButton.node).active = false;
            find('normal/numNode', this.swapperButton.node).active = true;
            find('normal/numNode/value', this.swapperButton.node).getComponent(Label).string = `${udm.itemSwapper.value}`;
        } else {
            find('normal/plus', this.swapperButton.node).active = true;
            find('normal/numNode', this.swapperButton.node).active = false;
        }
        if (udm.itemMagnet.value > 0) {
            find('normal/plus', this.magnetButton.node).active = false;
            find('normal/numNode', this.magnetButton.node).active = true;
            find('normal/numNode/value', this.magnetButton.node).getComponent(Label).string = `${udm.itemMagnet.value}`;
        } else {
            find('normal/plus', this.magnetButton.node).active = true;
            find('normal/numNode', this.magnetButton.node).active = false;
        }
        if (udm.itemBalloon.value > 0) {
            find('normal/plus', this.balloonButton.node).active = false;
            find('normal/numNode', this.balloonButton.node).active = true;
            find('normal/numNode/value', this.balloonButton.node).getComponent(Label).string = `${udm.itemBalloon.value}`;
        } else {
            find('normal/plus', this.balloonButton.node).active = true;
            find('normal/numNode', this.balloonButton.node).active = false;
        }
    }

    swapperButtonClicked() {
        let curStageId = this.stageView.stageInfo.stageId;
        if (curStageId >= DevConfig.ITEM_PARAM['swapper'].start_stage) {
            if (gm.balloonSelected.value) return;
            if (gm.swapperSelected.value) {
                gm.swapperSelected.value = false;
                gm.swapperSelectedIdx.value = null;
            } else {
                if (udm.itemSwapper.value <= 0) {
                    BuyItemPanel.StartProcess((panel: BuyItemPanel) => {
                        panel.itemKey.value = 'swapper';
                    }).subscribe(_ => {
                        if (_ == 'got') {
                            gm.swapperSelected.value = true;
                        }
                    });
                } else {
                    gm.swapperSelected.value = true;
                    gm.swapperSelectedIdx.value = null;
                }
            }
        } else {
            find('lock/locker', this.swapperButton.node).getComponent(Animation).play();
        }
    }

    magnetButtonClicked() {
        let curStageId = this.stageView.stageInfo.stageId;
        if (curStageId >= DevConfig.ITEM_PARAM['magnet'].start_stage) {

            if (gm.balloonSelected.value) return;
            if (gm.swapperSelected.value) return;

            if (gm.magnetSelected.value == false) {
                if (udm.itemMagnet.value <= 0) {
                    BuyItemPanel.StartProcess((panel: BuyItemPanel) => {
                        panel.itemKey.value = 'magnet';
                    }).subscribe(_ => {
                        if (_ == 'got') {
                            gm.magnetSelected.value = true;
                        }
                    });
                } else {
                    gm.magnetSelected.value = true;
                }
            } else {
                gm.magnetSelected.value = false;
            }
        } else {
            find('lock/locker', this.magnetButton.node).getComponent(Animation).play();
        }
    }

    balloonButtonClicked() {
        let curStageId = this.stageView.stageInfo.stageId;
        if (curStageId >= DevConfig.ITEM_PARAM['balloon'].start_stage) {
            if (gm.swapperSelected.value) return;
            if (gm.balloonSelected.value) {
                gm.balloonSelected.value = false;
            } else {
                if (udm.itemBalloon.value <= 0) {
                    BuyItemPanel.StartProcess((panel: BuyItemPanel) => {
                        panel.itemKey.value = 'balloon';
                    }).subscribe(_ => {
                        if (_ == 'got') {
                            gm.balloonSelected.value = true;
                        }
                    });
                } else {
                    gm.balloonSelected.value = true;
                }
            }
        } else {
            find('lock/locker', this.balloonButton.node).getComponent(Animation).play();
        }
    }

    _sub_smoke_list: Set<Subscription> = new Set();
    genChangeSmoke(param: { worldPos: Vec3 }) {
        let smokeNode = ResourceHelper.ChangeSmokePool.getNode();
        smokeNode.setParent(this.fxContainer);
        smokeNode.setWorldPosition(param.worldPos);
        let ps = smokeNode.getComponent(ParticleSystem);
        ps.play();
        let sub = Timer(1, smokeNode).subscribe(_ => {
            ps.stop();
            ResourceHelper.ChangeSmokePool.putNode(smokeNode);
            this._sub_smoke_list.delete(sub);
        });
        this._sub_smoke_list.add(sub);
    }

    burst0(worldPos: Vec3, colorId: number) {
        let node = ResourceHelper.Burst0Pool.getNode();
        let burst = node.getComponent(Burst0);
        burst.colorId = colorId;
        node.setParent(this.fxContainer);
        node.setWorldPosition(worldPos);
        burst.burst();
    }


}

